# 用户地址信息的ORM模型

from datetime import  datetime
from enum import IntEnum
from sqlalchemy.orm import declarative_base,relationship,backref
from sqlalchemy import Column,Integer,String,SmallInteger,DateTime,Boolean,Enum,ForeignKey

# 如果sqlalchemy没有对应的类型 可以使用以下两种方式 导入类型
# 第一种方式导入CHAR
from sqlalchemy.types import CHAR
# 第二种方式导入CHAR
from sqlalchemy.dialects.mysql import TINYINT



# 第二步，声明ORM模型的基类
Base = declarative_base()


class SexEnum(IntEnum):
    MAN = 1     #男
    WOMEN = 2   #女

class User(Base):
    # 用户信息表
    __tablename__ = 'account_user'
    id = Column('id',type_=Integer(),primary_key=True)
    username = Column(String(32),nullable=False,unique=True,comment='用户名')
    password = Column(String(512), nullable=False, comment='密码')
    real_name = Column(String(16), comment='真实姓名')
    sex = Column(Enum(SexEnum), default=None, comment='性别')
    # age = Column(SmallInteger, default=0,comment='年龄')
    age = Column(TINYINT(unsigned=True), default=0, comment='年龄')
    created_at = Column(DateTime,default=datetime.now(), comment='创建时间')
    is_valid = Column(Boolean,default=True, comment='是否有效')

    # 创建User表对UserProfile表（一对一的关系）（一对一关系在主表创建反向引用，在子表创建外键关联（也可以在子表创建反向引用，写法不同）。user是主表，UserProfile是子表）

    # 希望通过UserProfile也能访问到User  需要建立一个反向引用
    # obj_User = User ()
    # obj_User.profile
    # obj_User.profile.id
    # 也可以通过User也能访问到UserProfile
    # profile = UserProfile()
    # profile.user
    # profile.user.id
    # 一对一 反向引用的主表写法
    profile = relationship('UserProfile',backref='user',uselist=False)

    # 重写__repr__方法,print() 打印User的时候就会调用
    def __repr__(self):
        return '{}:{} => {}'.format(self.id,self.username,self.real_name)

class UserProfile(Base):
    # 用户详细信息表
    __tablename__ = 'account_user_profile'
    id = Column('id', type_=Integer(), primary_key=True)
    hobby = Column(String(255),comment='用户的爱好')
    created_at = Column(DateTime, default=datetime.now(), comment='创建时间')
    # 用户的外键
    user_id = Column(Integer,ForeignKey(User.id),comment='关联的用户ID')
    # 一对一 反向引用的子表写法
    # user = relationship('User',backref=backref('profile',uselist=False))




class UserAddress(Base):
    # 地址信息表
    __tablename__ = 'account_user_address'
    id = Column(Integer, primary_key=True)
    area = Column(String(256), nullable=False,comment='地址信息')
    # phone_no = Column(String(11), comment='电话号码')
    phone_no = Column(CHAR(11), comment='电话号码')
    remark = Column(String(512), comment='备注信息')
    is_valid = Column(Boolean, default=True, comment='是否有效')
    created_at = Column(DateTime, default=datetime.now(), comment='创建时间')

    # 创建User表对UserAddress表（一对多的关系）（一对多关系在子表创建，user是主表，UserAddress是子表）
    user_id = Column(Integer,ForeignKey(User.id),comment='关联的用户ID')
    # user_id = Column(Integer, ForeignKey('account_user.id'), comment='关联的用户ID')

    # 希望通过User也能访问到UserAddress  需要建立一个反向引用
    # obj_user = User()
    # obj_user.addresses
    # obj_user.addresses.id
    # 但是不可以通过UserAddress也能访问到User  因为地一对多关系  只有一对一关系才可以
    # 以下写法是错误的 不可以
    # obj_userAddress = UserAddress() 错误
    # obj_userAddress.user 错误
    # obj_userAddress.user.id 错误
    # user = relationship('User',backref='addresses') #<class 'sqlalchemy.orm.collections.InstrumentedList'>
    # 这种写法可以在反向查询出List类型的时候  使用filter等方法
    user = relationship('User',backref=backref('addresses',lazy='dynamic')) #<class 'sqlalchemy.orm.dynamic.AppenderQuery'>


def create_table():
    # 创建表
    from db_engine import engine
    Base.metadata.create_all(engine)


def drop_table():
    # 删除表
    from db_engine import engine
    Base.metadata.drop_all(engine)

